package com.example.userservice.service.impl;

import com.example.userservice.dto.LoginRequest;
import com.example.userservice.dto.UserRegistrationRequest;
import com.example.userservice.dto.UserResponse;
import com.example.userservice.entity.Role;
import com.example.userservice.entity.User;
import com.example.userservice.mapper.UserMapper;
import com.example.userservice.security.JwtUtil;
import com.example.userservice.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

import com.example.userservice.dto.AssignRoleRequest;
import com.example.userservice.feign.PermissionServiceClient;
import com.example.userservice.config.RabbitMQConfig;
import com.example.userservice.dto.LogMessage;

@Service
@RequiredArgsConstructor
@Slf4j
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;
    private final PasswordEncoder passwordEncoder;
    private final JwtUtil jwtUtil;
    private final AuthenticationManager authenticationManager;
    private final UserDetailsService userDetailsService;
    private final PermissionServiceClient permissionServiceClient;
    private final RabbitTemplate rabbitTemplate;

    // 用于替代分布式ID生成器的占位符
    private final AtomicLong idGenerator = new AtomicLong(System.currentTimeMillis());

    @Override
    public String login(LoginRequest loginRequest) {
        authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())
        );
        final UserDetails userDetails = userDetailsService.loadUserByUsername(loginRequest.getUsername());
        return jwtUtil.generateToken(userDetails);
    }

    @Override
    @Transactional
    public UserResponse register(UserRegistrationRequest request) {
        if (userMapper.findByUsername(request.getUsername()).isPresent()) {
            throw new IllegalStateException("用户名已存在");
        }

        User user = new User();
        // 在真正的分布式系统中, 这里应该使用雪花算法等分布式ID生成器
        long userId = idGenerator.incrementAndGet();
        user.setUserId(userId);
        user.setUsername(request.getUsername());
        user.setPassword(passwordEncoder.encode(request.getPassword()));
        user.setEmail(request.getEmail());
        user.setPhone(request.getPhone());
        user.setGmtCreate(LocalDateTime.now());

        userMapper.save(user);

        try {
            permissionServiceClient.bindDefaultRole(user.getUserId());
            log.info("成功为用户 {} 绑定默认角色", user.getUsername());
        } catch (Exception e) {
            log.error("调用权限服务为用户 {} 绑定角色失败", user.getUsername(), e);
            // 这里通常会抛出一个自定义异常来触发事务回滚
            throw new RuntimeException("绑定角色失败，注册流程无法继续", e);
        }

        try {
            // 此处假设无法获取IP地址，因此传递null。
            // 在真实应用中，您会从Controller的HttpServletRequest中获取IP。
            LogMessage logMessage = new LogMessage(
                    user.getUserId(),
                    "REGISTER",
                    null, // IP 地址
                    "新用户注册"
            );
            rabbitTemplate.convertAndSend(RabbitMQConfig.LOG_QUEUE, logMessage);
            log.info("已发送用户注册日志消息，用户: {}", user.getUsername());
        } catch (Exception e) {
            log.error("发送用户注册日志消息失败，用户: {}", user.getUsername(), e);
            // 记录日志失败不影响主事务，所以只记录错误
        }

        return toUserResponse(user);
    }

    @Override
    public List<UserResponse> getAllUsers() {
        return userMapper.findAll().stream()
                .map(this::toUserResponse)
                .collect(Collectors.toList());
    }

    @Override
    public UserResponse getUserById(Long id) {
        return userMapper.findById(id)
                .map(this::toUserResponse)
                .orElseThrow(() -> new UsernameNotFoundException("用户未找到, ID: " + id));
    }

    @Override
    public UserResponse updateUser(Long id, UserRegistrationRequest request) {
        User user = userMapper.findById(id)
                .orElseThrow(() -> new UsernameNotFoundException("用户未找到, ID: " + id));

        // 如果请求中包含相应字段，则更新
        if (request.getUsername() != null && !request.getUsername().isEmpty()) {
            // 在实际应用中，可能还需要检查用户名是否已被占用
            user.setUsername(request.getUsername());
        }
        if (request.getEmail() != null && !request.getEmail().isEmpty()) {
            user.setEmail(request.getEmail());
        }
        if (request.getPhone() != null && !request.getPhone().isEmpty()) {
            user.setPhone(request.getPhone());
        }
        // 仅在提供了新密码时才更新
        if (request.getPassword() != null && !request.getPassword().isEmpty()) {
            user.setPassword(passwordEncoder.encode(request.getPassword()));
        }

        userMapper.update(user);
        return toUserResponse(user);
    }

    @Override
    public void resetPassword(Long id, String newPassword) {
        User user = userMapper.findById(id)
                .orElseThrow(() -> new UsernameNotFoundException("用户未找到, ID: " + id));
        user.setPassword(passwordEncoder.encode(newPassword));
        userMapper.update(user);
    }

    private User getCurrentUser() {
        String username = SecurityContextHolder.getContext().getAuthentication().getName();
        return userMapper.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("当前用户在数据库中未找到"));
    }

    private UserResponse toUserResponse(User user) {
        UserResponse userResponse = new UserResponse();
        userResponse.setUserId(user.getUserId());
        userResponse.setUsername(user.getUsername());
        userResponse.setEmail(user.getEmail());
        userResponse.setPhone(user.getPhone());
        userResponse.setGmtCreate(user.getGmtCreate());
        
        // 从权限服务获取角色信息
        try {
            String roleCode = permissionServiceClient.getUserRoleCode(user.getUserId());
            userResponse.setRole(roleCode);
        } catch (Exception e) {
            log.error("为用户 {} 获取角色信息失败", user.getUsername(), e);
            userResponse.setRole("角色获取失败");
        }
        
        return userResponse;
    }
} 